<template>
  <div class="map-container">
    <div class="map-header">
      <ElInput
        v-model="searchKeyword"
        placeholder="输入地点名称，如'天安门'"
        clearable
        @keydown.enter.prevent.native="handleSearch"
        @keyup.enter.prevent.native="handleSearch"
        class="search-input"
        @clear="handleClearSearch"
      >
        <template #append>
          <ElButton type="primary" @click="debouncedHandleSearch" icon="Search"
            >搜索</ElButton
          >
        </template>
      </ElInput>
      <!-- 添加手动定位按钮 -->
      <ElButton
        type="primary"
        @click="debouncedTriggerGeolocation"
        icon="Location"
        class="locate-button"
      >
        定位
      </ElButton>
    </div>
    <div id="map-container" ref="mapContainer"></div>

    <div class="search-results" v-show="searchResults.length > 0 || isLoading">
      <ElCard shadow="hover">
        <template #header>
          <div class="flex items-center justify-between">
            <h3>搜索结果</h3>
            <ElIcon v-if="isLoading" class="is-loading">
              <Loading />
            </ElIcon>
          </div>
        </template>
        <ElScrollbar height="300px">
          <template v-if="!isLoading">
            <div
              v-for="(item, index) in searchResults"
              :key="index"
              class="result-item"
              @click="centerToLocation(item)"
            >
              <div class="result-name">
                <ElIcon class="location-icon">
                  <Location />
                </ElIcon>
                {{ item.name }}
              </div>
              <div class="result-address">{{ item.address }}</div>
              <div class="result-distance" v-if="item.distance">
                <ElIcon>
                  <Position />
                </ElIcon>
                距离: {{ (item.distance / 1000).toFixed(1) }}公里
              </div>
            </div>
          </template>
          <div v-else class="loading-text">搜索中...</div>
        </ElScrollbar>
      </ElCard>
    </div>
  </div>
</template>
<script type="text/javascript">
// 必须在AMap JS加载前设置安全配置
window._AMapSecurityConfig = {
  securityJsCode: mapSetting.mapSecurity || "",
};
</script>
<script setup>
import {
  ref,
  onMounted,
  onBeforeUnmount,
  watch,
  computed,
  defineProps,
  defineEmits,
} from "vue";
import AMapLoader from "@amap/amap-jsapi-loader";
import {
  ElMessage,
  ElInput,
  ElButton,
  ElScrollbar,
  ElCard,
  ElIcon,
} from "element-plus";
import { Loading, Location, Position } from "@element-plus/icons-vue";
import { mapSetting } from "#/api/map";
import { useDebounceFn } from "@vueuse/core";

// 地图实例
const map = ref(null);
const mapContainer = ref(null);
const placeSearch = ref(null);
const marker = ref(null);
const point = ref([]);
const geocoder = ref();
const AMapInstance = ref(null); // 保存AMap实例

// 检查是否在安全上下文中
const isSecureContext = window.isSecureContext || 
  window.location.protocol === 'https:' || 
  window.location.hostname === 'localhost' || 
  window.location.hostname === '127.0.0.1';

// 在页面加载后延迟触发位置请求
const requestLocationPermission = () => {
  if (!isSecureContext) {
    ElMessage.error({
      message: '地理位置功能需要HTTPS协议或localhost环境才能使用',
      duration: 8000,
      showClose: true
    });
    return;
  }
  
  if (navigator.geolocation) {
    // 添加用户交互事件监听
    document.addEventListener('click', () => {
      navigator.geolocation.getCurrentPosition(
        (position) => {
          console.log("用户已允许位置权限", position);
        },
        (error) => {
          if (error.code === error.PERMISSION_DENIED) {
            ElMessage.warning({
              message: "请点击页面任意位置后允许位置权限，或手动点击定位按钮",
              duration: 5000,
              showClose: true,
            });
          } else if (error.code === error.POSITION_UNAVAILABLE) {
            ElMessage.error({
              message: '无法获取位置信息，请检查网络连接',
              duration: 5000,
              showClose: true
            });
          }
        },
        { enableHighAccuracy: true, timeout: 5000 }
      );
    }, { once: true });
  } else {
    ElMessage.error("您的浏览器不支持地理位置功能");
  }
};

// 页面加载后延迟执行
setTimeout(requestLocationPermission, 1000);

const props = defineProps({
  data: {
    type: Object,
    default: () => ({
      defaultAddress: "",
      defaultPoint: [],
    }),
  },
});

// 计算属性获取点坐标
const defaultPoint = computed(
  () => props.data?.defaultPoint || [116.397428, 39.90923]
);
const defaultAddress = computed(() => props.data?.defaultAddress || "");

const emits = defineEmits(["getPosition"]);

// 搜索相关
const searchKeyword = ref("");
const searchResults = ref([]);
const address = ref(""); // 地址

// 添加一个新的函数来处理定位权限提示
const showLocationPermissionPrompt = () => {
  ElMessage.warning({
    message: "请允许浏览器访问您的位置信息，以便进行定位",
    duration: 5000,
    showClose: true,
  });
};

// 初始化地图
// 初始化地图
const initMap = async () => {
  try {
    const AMap = await AMapLoader.load({
      key: mapSetting.mapKey,
      securityJsCode: mapSetting.mapSecurity,
      version: "2.0",
      plugins: [
        "AMap.PlaceSearch",
        "AMap.Geocoder",
        "AMap.AutoComplete",
        "AMap.ToolBar",
        "AMap.Scale",
        "AMap.Marker",
        "AMap.Geolocation",
      ],
    });

    // 保存AMap实例以便在其他函数中使用
    AMapInstance.value = AMap;
    point.value = defaultPoint.value;
    const center = defaultPoint.value?.[0]
      ? defaultPoint.value
      : [116.397428, 39.90923];
    // 创建地图实例
    map.value = new AMap.Map(mapContainer.value, {
      zoom: 13,
      center,
      viewMode: "2D",
    });
    // 初始化地点搜索
    placeSearch.value = new AMap.PlaceSearch({
      map: map.value,
      pageSize: 10,
      pageIndex: 1,
      city: "全国",
    });
    // 初始化地理编码器
    geocoder.value = new AMap.Geocoder({
      city: "010", //城市设为北京，默认：“全国”
      radius: 1000, //范围，默认：500
    });
    // 添加定位控件
    const geolocation = new AMap.Geolocation({
      enableHighAccuracy: true,
      timeout: 10000,
      buttonPosition: "RB",
      showButton: true,
      panToLocation: true,
      zoomToAccuracy: true,
    });

    // 更安全地处理事件监听
    try {
      // 尝试使用 AMap.event
      if (AMap.event && typeof AMap.event.addListener === "function") {
        // 监听定位事件
        AMap.event.addListener(geolocation, "complete", (result) => {
          console.log("定位成功:", result);
          ElMessage.success("定位成功");
        });

        AMap.event.addListener(geolocation, "error", (error) => {
          console.error("定位失败:", error);
          // 根据错误类型给出相应提示
          if (error.info === "FAILED" || error.info === "TIMEOUT") {
            ElMessage.error("定位失败，请检查网络连接或位置服务是否开启");
          } else if (error.info === "PERMISSION_DENIED") {
            showLocationPermissionPrompt();
          } else {
            ElMessage.error("定位失败: " + error.message);
          }
        });
      } else {
        // 如果 AMap.event 不可用，尝试直接在控件上绑定事件
        if (geolocation.on) {
          geolocation.on("complete", (result) => {
            console.log("定位成功:", result);
            ElMessage.success("定位成功");
          });

          geolocation.on("error", (error) => {
            console.error("定位失败:", error);
            if (error.info === "PERMISSION_DENIED") {
              showLocationPermissionPrompt();
            } else {
              ElMessage.error(
                "定位失败: " + "获取ipLocation失败。请开启地理定位权限"
              );
            }
          });
        } else {
          console.warn("无法绑定定位事件监听器");
        }
      }
    } catch (eventError) {
      console.warn("绑定事件监听器时出错:", eventError);
    }

    map.value.addControl(geolocation);
    addMarker();
    // 地图点击事件
    map.value.on("click", clickMapHandler);
  } catch (error) {
    console.error("地图初始化失败:", error);
    ElMessage.error("地图初始化失败: " + error.message);
  }
};

// 添加一个手动触发定位的函数
const triggerGeolocation = () => {
  if (!map.value || !AMapInstance.value) {
    ElMessage.error('地图未初始化完成');
    return;
  }

  // 创建新的定位实例并执行定位
  createNewGeolocation();
};

const debouncedTriggerGeolocation = useDebounceFn(triggerGeolocation, 500);


const createNewGeolocation = () => {
  if (!AMapInstance.value) {
    ElMessage.error("地图API未正确加载");
    return;
  }

  try {
    const geolocation = new AMapInstance.value.Geolocation({
      enableHighAccuracy: true,
      timeout: 10000,
      showButton: false, // 不显示按钮
    });

    // 执行定位
    if (typeof geolocation.getCurrentPosition === "function") {
      geolocation.getCurrentPosition((status, result) => {
        handleGeolocationResult(status, result);
      });
    } else {
      // 如果没有 getCurrentPosition 方法，尝试其他方式
      ElMessage.error("当前环境不支持定位功能");
    }
  } catch (error) {
    console.error("创建定位实例失败:", error);
    ElMessage.error("定位功能初始化失败: " + error.message);
  }
};

// 处理定位结果的通用函数
const handleGeolocationResult = (status, result) => {
  if (status === "complete") {
    ElMessage.success("定位成功");
    // 更新地图中心点
    point.value = [result.position.lng, result.position.lat];
    map.value.setCenter(point.value);
    addMarker();
    getAddress();
  } else {
    console.error("定位失败:", result);
    if (result.info === "PERMISSION_DENIED") {
      showLocationPermissionPrompt();
    } else if (result.info === "TIMEOUT") {
      ElMessage.error("定位超时，请检查网络连接或位置服务是否开启");
    } else {
      ElMessage.error("定位失败: " + result.message);
    }
  }
};

// 执行搜索
const isLoading = ref(false);
const handleClearSearch = () => {
  searchResults.value = [];
  searchKeyword.value = "";
  isLoading.value = false;
};

const handleSearch = () => {
  const keyword = searchKeyword.value.trim();
  if (!keyword) {
    ElMessage.warning("请输入搜索关键词");
    return;
  }

  isLoading.value = true;
  searchResults.value = [];

  // 设置PlaceSearch的事件监听
  if (placeSearch.value) {
    try {
      // 检查AMapInstance.value.event是否可用
      if (AMapInstance.value && AMapInstance.value.event) {
        // 移除之前的事件监听（如果有）
        try {
          AMapInstance.value.event.removeListener(
            placeSearch.value,
            "markerClick"
          );
        } catch (error) {
          console.warn("移除事件监听失败，可能是之前没有添加过:", error);
        }
        // 添加标记点击事件
        AMapInstance.value.event.addListener(
          placeSearch.value,
          "markerClick",
          (e) => {
            if (e && e.data) {
              const poi = e.data;
              // 更新搜索框
              searchKeyword.value = poi.name;
              // 保存位置信息
              const markerPosition = [poi.location.lng, poi.location.lat];
              point.value = markerPosition;
              // 获取地址信息
              getAddress();
              // 关闭搜索结果面板
              searchResults.value = [];
            }
          }
        );
      } else {
        // 备用方法：在搜索完成后，为所有标记添加点击事件
        setTimeout(() => {
          const markers = map.value.getAllOverlays("marker");
          markers.forEach((marker) => {
            // 为每个标记添加点击事件
            marker.on("click", (e) => {
              // 获取标记的位置
              const position = marker.getPosition();
              const markerPosition = [position.getLng(), position.getLat()];
              // 更新当前位置
              point.value = markerPosition;
              // 移动地图中心点
              map.value.setCenter(markerPosition);
              // 获取地址信息
              getAddress();
              // 尝试查找与此标记位置匹配的搜索结果
              const matchingResult = searchResults.value.find((item) => {
                const itemLng = item.location.lng;
                const itemLat = item.location.lat;
                // 使用近似比较，因为浮点数可能有微小差异
                return (
                  Math.abs(itemLng - position.getLng()) < 0.0001 &&
                  Math.abs(itemLat - position.getLat()) < 0.0001
                );
              });
              // 如果找到匹配的搜索结果，更新搜索框
              if (matchingResult) {
                searchKeyword.value = matchingResult.name;
              }
              // 关闭搜索结果面板
              searchResults.value = [];
            });
          });
        }, 500);
      }
    } catch (error) {
      console.error("设置PlaceSearch事件监听失败:", error);
    }
  }

  // 执行搜索
  placeSearch.value.search(keyword, (status, result) => {
    isLoading.value = false;

    if (status === "complete" && result.poiList?.pois) {
      searchResults.value = result.poiList.pois;
      if (searchResults.value.length === 0) {
        ElMessage.info("未找到相关地点");
      }
    } else {
      const errorMsg = result?.info || "搜索失败";
      ElMessage.error(errorMsg);
      console.error("搜索出错:", errorMsg);
      searchResults.value = [];
    }
  });
};

const debouncedHandleSearch = useDebounceFn(handleSearch, 500);

// 将经纬度转换为地址
const getAddress = () => {
  geocoder.value.getAddress(point.value, (status, result) => {
    if (status === "complete" && result.regeocode) {
      address.value = result.regeocode.formattedAddress;
      emits("getPosition", {
        defaultAddress: result.regeocode.formattedAddress,
        defaultPoint: point.value,
      });
    } else {
      let errorMsg = "地理编码失败";
      if (result?.info === "INVALID_USER_KEY") {
        errorMsg = "高德地图API密钥无效，请检查配置";
      } else if (result?.info === "DAILY_QUERY_OVER_LIMIT") {
        errorMsg = "高德地图API调用已达日限额";
      }
      ElMessage.error(errorMsg);
      console.error("地理编码失败", result);
    }
  });
};

// 增加点标记
const addMarker = () => {
  // 清除其他icon
  if (marker.value) {
    marker.value.setMap(null);
    marker.value = null;
  }
  // 重新渲染icon
  marker.value = new AMapInstance.value.Marker({
    position: point.value, // icon经纬度
    offset: new AMapInstance.value.Pixel(-13, -30), // icon中心点的偏移量
    icon: new AMapInstance.value.Icon({
      image:
        "//a.amap.com/jsapi_demos/static/demo-center/icons/poi-marker-default.png",
      size: new AMapInstance.value.Size(30, 40), // 图标大小
      imageSize: new AMapInstance.value.Size(30, 40),
    }),
    clickable: true, // 确保标记可点击
    cursor: "pointer", // 鼠标悬停时显示手型光标
  });
  marker.value.setMap(map.value); // 设置icon
};

const clickMapHandler = (e) => {
  const lng = e.lnglat.lng;
  const lat = e.lnglat.lat;
  point.value = [lng, lat];
  map.value?.setCenter(point.value);
  // 增加点标记
  addMarker();
  getAddress();
};

// 定位到指定位置
const centerToLocation = (poi) => {
  searchResults.value = [];
  isLoading.value = false;
  if (!map.value) return;

  // 清除旧标记
  if (marker.value) {
    map.value.remove(marker.value);
    marker.value = null;
  }

  // 保存位置信息，以便在点击事件中使用
  const markerPosition = [poi.location.lng, poi.location.lat];

  // 创建新标记，并在创建时直接绑定点击事件
  if (AMapInstance.value) {
    marker.value = new AMapInstance.value.Marker({
      position: markerPosition,
      map: map.value,
      clickable: true, // 确保标记可点击
      cursor: "pointer", // 鼠标悬停时显示手型光标
      bubble: false, // 关闭事件冒泡，防止点击事件被地图捕获
    });
  } else {
    console.error("AMap实例不可用，无法创建标记");
    return;
  }

  // 移动地图中心点
  map.value.setCenter(markerPosition);
  map.value.setZoom(15);
  searchKeyword.value = poi.name;
  emits("getPosition", {
    defaultAddress: poi.name,
    defaultPoint: markerPosition,
  });
};

const isMounted = ref(false);

// 监听props.data变化
watch(
  () => props.data,
  (newVal) => {
    if (isMounted.value && newVal?.defaultPoint) {
      if (map.value) {
        // 已有地图实例则更新中心点
        map.value.setCenter(newVal.defaultPoint);
        point.value = newVal.defaultPoint;
        addMarker();
      } else {
        // 无地图实例则初始化
        initMap();
      }
    }
  },
  { deep: true, immediate: true }
);

onMounted(() => {
  isMounted.value = true;
  // showLocationPermissionPrompt();
  // 自动触发定位
  // triggerGeolocation();
  // 确保有默认值才初始化
  if (props.data.defaultPoint && props.data.defaultPoint.length === 2) {
    initMap();
  } else {
    console.warn("等待有效的地图中心点坐标");
  }
});

onBeforeUnmount(() => {
  // 清理地图
  if (map.value) {
    map.value.destroy();
  }
});
</script>

<style scoped>
.map-container {
  position: relative;
  width: 100%;
  height: 400px;
}

#map-container {
  width: 100%;
  height: 100%;
}

.map-header {
  position: absolute;
  top: 20px;
  left: 20px;
  z-index: 999;
  width: 400px;
  display: flex;
  gap: 10px;
}

.search-input {
  border-radius: var(--el-input-border-radius, var(--el-border-radius-base));
  box-shadow: 0 2px 6px rgb(0 0 0 / 30%);
  flex: 1;
}

.locate-button {
  height: 32px;
  align-self: center;
}

.search-results {
  position: absolute;
  top: 60px;
  left: 20px;
  z-index: 999;
  width: 400px;
}

.result-item {
  padding: 12px 16px;
  cursor: pointer;
  border-bottom: 1px solid var(--el-border-color-light);
  transition: all 0.3s ease;
}

.result-item:hover {
  background-color: var(--el-color-primary-light-9);
  transform: translateX(4px);
}

.result-name {
  display: flex;
  align-items: center;
  font-weight: bold;
  color: var(--el-text-color-primary);
}

.location-icon {
  margin-right: 8px;
  color: var(--el-color-primary);
}

.result-address {
  margin-left: 24px;
  font-size: 12px;
  color: var(--el-text-color-secondary);
}

.result-distance {
  display: flex;
  align-items: center;
  margin-left: 24px;
  font-size: 12px;
  color: var(--el-color-primary);
}

.result-distance .el-icon {
  margin-right: 4px;
}

.loading-text {
  padding: 20px;
  color: var(--el-text-color-secondary);
  text-align: center;
}

:deep(.el-card__body) {
  padding: 0;
}
</style>
